package com.brillilab.starter.controller.aio.space;

import com.brillilab.common.constant.ResultEnum;
import com.brillilab.common.entity.ResponseVo;
import com.brillilab.common.exceptions.BrillilabException;
import com.brillilab.domain.enums.common.IsDeleteEnum;
import com.brillilab.domain.po.lab.Lab;
import com.brillilab.domain.po.lab.LabMember;
import com.brillilab.domain.po.space.Box;
import com.brillilab.domain.po.space.Panel;
import com.brillilab.domain.po.space.PanelGridUsed;
import com.brillilab.domain.po.system.Dict;
import com.brillilab.domain.po.user.Users;
import com.brillilab.domain.vo.space.BoxAdd;
import com.brillilab.domain.vo.space.BoxModify;
import com.brillilab.domain.vo.space.BoxVo;
import com.brillilab.domain.vo.user.UserInfoVo;
import com.brillilab.service.core.lab.ILabMemberService;
import com.brillilab.service.core.lab.ILabService;
import com.brillilab.service.core.space.IBoxService;
import com.brillilab.service.core.space.IPanelService;
import com.brillilab.service.core.system.IDictService;
import com.brillilab.service.logic.space.BoxLogic;
import com.brillilab.service.logic.space.PanelLogic;
import com.brillilab.service.logic.user.UsersLogic;
import com.brillilab.service.module.message.producer.MessageProducer;
import com.brillilab.service.module.message.template.impl.space.PrivateReagentBoxModifyTemp;
import com.brillilab.service.module.message.template.impl.space.PrivateReagentBoxModifyToPrivateTemp;
import com.brillilab.service.module.message.template.impl.space.ReagentBoxToPrivateTemp;
import com.brillilab.starter.aspect.AspectLog;
import com.brillilab.starter.constant.StarterConstant;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author wuzhiyu
 * @Title: Box
 * @ProjectName brill_lab
 * @Description: TODO
 * @date 2018/11/139:29
 */
@RestController
@RequestMapping("/api/spaceManage/box")
public class BoxController {
    @Autowired
    private IBoxService boxService;
    @Autowired
    private IPanelService panelService;
    @Autowired
    private UsersLogic usersLogic;
    @Autowired
    private BoxLogic boxLogic;
    @Autowired
    private IDictService dictService;
    @Autowired
    private ILabMemberService labMemberService;
    @Autowired
    private PanelLogic panelLogic;
    @Resource
    private ILabService labService;
    @Resource
    private MessageProducer messageProducer;

    @AspectLog
    @PostMapping("/add")
    public ResponseVo add(@RequestBody BoxAdd boxAdd, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(boxAdd, "数据为空");
        Assert.notNull(boxAdd.getPanelId(), "panelId is null");
        Assert.notNull(boxAdd.getBoxColor(), "box Color is null ");
        Assert.notNull(boxAdd.getColumns(), "box columns is null");
        Assert.notNull(boxAdd.getRows(), "box rows is null");
        Assert.notNull(boxAdd.getHeight(), "box height is null");
        Assert.notNull(boxAdd.getWidth(), "box width is null");
        Assert.notNull(boxAdd.getX(), "box x is null ");
        Assert.notNull(boxAdd.getY(), "box y is null");
        Assert.notNull(boxAdd.getSpec(), "box spec is null");
        Panel panel = panelService.get(boxAdd.getPanelId());
        Assert.notNull(panel, "data not exist");
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!panel.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        List<BoxVo> boxList = boxService.list(panel.getId());
        if (boxList.stream().filter(b -> b.getBoxColor().equals(boxAdd.getBoxColor())).count() > 0) {
            throw new BrillilabException(ResultEnum.DATA_ALREADY_EXIST);
        }
        BoxVo boxVo = boxLogic.add(boxAdd, panel, info);
        return ResponseVo.success(boxVo);
    }

    @AspectLog
    @DeleteMapping("/delete")
    public ResponseVo delete(Long id, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(id, "id is null");
        Box box = boxService.get(id);
        Assert.notNull(box, "data not exist");
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!box.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return boxLogic.delete(box.getId()) ? ResponseVo.success() : ResponseVo.failure();
    }

    @AspectLog
    @PutMapping("/edit")
    public ResponseVo edit(@RequestBody BoxModify modify, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(modify, "data is null");
        Assert.notNull(modify.getId(), "data id is null");
        Box box = boxService.get(modify.getId());

        Assert.notNull(box, "data not exist");
        Assert.isTrue(box.getIsDelete().equals(IsDeleteEnum.NO.getValue()), "box not exist");
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!box.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        modify.setId(box.getId());
        boolean update = boxLogic.updateBox(modify);
        if (update) {
            //原平面试剂盒所有者
            Long oldLabMemberId = box.getLabMemberId();
            LabMember old = null;
            if (oldLabMemberId != null) {
                old = labMemberService.selectById(oldLabMemberId);
            }
            LabMember current = null;
            if (modify.getLabMemberId() != null) {
                current = labMemberService.selectById(modify.getLabMemberId());
            }
            Lab lab = labService.selectById(box.getLabId());
            if (old != null) {
                if (current == null) {
                    if (!info.getId().equals(old.getUserId())) {
                        //私有变公共
                        PrivateReagentBoxModifyTemp privateReagentBoxModifyTemp = new PrivateReagentBoxModifyTemp(box.getLabId(), old.getUserId(), oldLabMemberId, lab.getName(), box.getDeviceIndex(), box.getPanelName(), box.getBoxColor());
                        messageProducer.sendMessagePush(privateReagentBoxModifyTemp);
                    }
                } else {
                    if (!old.getUserId().equals(current.getUserId())) {
                        if (!info.getId().equals(old.getUserId())) {
                            //发现所有者，通知被修改人
                            Users newUser = usersLogic.getUser(current.getUserId());
                            PrivateReagentBoxModifyToPrivateTemp privateReagentBoxModifyToPrivateTemp = new PrivateReagentBoxModifyToPrivateTemp(box.getLabId(), old.getUserId(), oldLabMemberId, lab.getName(), box.getDeviceIndex(), box.getPanelName(), box.getBoxColor(), newUser.getName());
                            messageProducer.sendMessagePush(privateReagentBoxModifyToPrivateTemp);
                        }
                        if (!info.getId().equals(current.getUserId())) {
                            //发现所有者,通知当前试剂所有者
                            ReagentBoxToPrivateTemp reagentBoxToPrivateTemp = new ReagentBoxToPrivateTemp(box.getLabId(), current.getUserId(), modify.getLabMemberId(), lab.getName(), box.getDeviceIndex(), box.getPanelName(), box.getBoxColor(), info.getName());
                            messageProducer.sendMessagePush(reagentBoxToPrivateTemp);
                        }
                    }
                }
            } else {
                if (current != null && !info.getId().equals(current.getUserId())) {
                    //发现所有者，通知当前试剂所有者
                    ReagentBoxToPrivateTemp reagentBoxToPrivateTemp = new ReagentBoxToPrivateTemp(box.getLabId(), current.getUserId(), modify.getLabMemberId(), lab.getName(), box.getDeviceIndex(), box.getPanelName(), box.getBoxColor(), info.getName());
                    messageProducer.sendMessagePush(reagentBoxToPrivateTemp);
                }
            }
        }
        return update ? ResponseVo.success() : ResponseVo.failure();
    }

    @AspectLog
    @PostMapping("/update")
    public ResponseVo update(@RequestBody List<PanelGridUsed> panelGridUsedList, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(panelGridUsedList, "data is null");
        Assert.isTrue(panelGridUsedList.size() > 0, "list is empty");
        Assert.notNull(panelGridUsedList.get(0).getBoxId(), "box id is null");
        Panel panel = panelService.get(panelGridUsedList.get(0).getPanelId());
        Assert.notNull(panel, "panel not exist");
        Assert.isTrue(panel.getIsDelete().equals(IsDeleteEnum.NO.getValue()), "Panel not exist");
        Box box = boxService.get(panelGridUsedList.get(0).getBoxId());
        Assert.notNull(box, "box not exist");
        Assert.isTrue(box.getIsDelete().equals(IsDeleteEnum.NO.getValue()), "box not exist");
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!panel.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return panelLogic.updateBoxPosition(box, null, panelGridUsedList) ? ResponseVo.success() : ResponseVo.failure();
    }

    @GetMapping("/gridList")
    public ResponseVo gridList(Long boxId, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(boxId, "data is null");
        Box box = boxService.get(boxId);
        Assert.notNull(box, "box not exist");
        if (box.getIsDelete().equals(IsDeleteEnum.YES.getValue())) {
            Assert.notNull(box, "box not exist");
        }
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!box.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return ResponseVo.success(boxLogic.getBoxWithGridList(box, info));
    }

    @GetMapping("/list")
    public ResponseVo list(Long panelId, @RequestHeader(value = StarterConstant.TOKEN) String token) {
        if (StringUtils.isBlank(token)) {
            throw new BrillilabException(ResultEnum.USER_NOT_LOGIN);
        }
        Assert.notNull(panelId, "data is null");
        Panel panel = panelService.get(panelId);
        Assert.notNull(panel, "panel not exist");
        UserInfoVo info = usersLogic.getUserByToken(token);
        if (!panel.getLabId().equals(info.getLabId())) {
            throw new BrillilabException(ResultEnum.USER_NOT_POWER);
        }
        return ResponseVo.success(boxLogic.getBoxlist(panel, info));
    }

    @GetMapping("/boxDict")
    public ResponseVo dict() {
        List<Dict> colorList = dictService.getBoxColor();
        List<Dict> sizeList = dictService.getBoxSize();
        List<Dict> tubeList = dictService.getTubeSize();
        Map<String, List<Dict>> map = new HashMap<>();
        map.put("color", colorList);
        map.put("box", sizeList);
        map.put("tube", tubeList);
        return ResponseVo.success(map);
    }
}
